// import { PlusSquareOutlined ,DeleteOutlined} from '@ant-design/icons';
import ROBOT_AVATAR from '@/assets/image/robot_avatar.png';
import ROBOT_AVATAR2 from '@/assets/image/robot_avatar2.png';
import USER_AVATAR from '@/assets/image/user_avatar.png';
import {
  conversations,
  getMessages,
  messages_comet,
  pollingMsg,
} from '@/services/ant-design-pro/chatBot';
import { isNotEmpty } from '@/utils/index';
import { LoadingOutlined } from '@ant-design/icons';
import { history } from '@umijs/max';
import { Button, Input, InputRef, message } from 'antd';
import { nanoid } from 'nanoid';
import React, { useEffect, useRef, useState } from 'react';
import './index.less';
import questionList from './questionList';

const Doc: React.FC = (props: any) => {
  const { id, changeNew, isCreateNew, changeHistoryList, isDelCur, knowledgeId } = props;
  interface DocCon {
    id?: string;
    conversation_id?: number;
    content?: string; // 内容
    role?: string; // 角色
    uuid?: string; // uuid
    created_at?: number; // 时间
  }
  const messagesEnd = useRef<HTMLDivElement>(null);
  const questionInput = useRef<InputRef>(null);
  const scrollToBottom = () => {
    if (messagesEnd && messagesEnd.current) {
      // messagesEnd.current.scrollIntoView({ behavior: 'auto' });
      messagesEnd.current.scrollTop = messagesEnd.current.scrollHeight;
    }
  };
  const [conversationID, setConversationID] = useState<number | string>(); //当前会话的id 没有先创建会话
  const [doc, setDoc] = useState<DocCon[]>([]);
  const [loading, setLoading] = useState<boolean>(false);
  const [ipt, setIpt] = useState<string>('');
  const [answering, setAnswering] = useState<boolean>(false); //是否正在回答中
  //创建对话信息
  // const handleCreateMessages = async (id: any, keyword: any) => {
  //   setLoading(true);
  //   setAnswering(true); //预先展示正在回答中
  //   //用户提出的问题
  //   const userQuestion = {
  //     id: nanoid(),
  //     uuid: nanoid(),
  //     content: keyword,
  //     role: 'user',
  //   };
  //   setDoc((prev: DocCon[]) => {
  //     return [...prev, userQuestion];
  //   });
  //   const body = {
  //     conversation_id: id,
  //     content: keyword,
  //   };

  //   const res = await createMessages(body);
  //   if (res.code === 0) {
  //     const message = res.data?.message;
  //     setLoading(false);
  //     setAnswering(false); //关闭正在回答中 展示后台返回的答案
  //     setIpt(''); //清空输入框
  //     //将用户的问题和机器人的回复添加到doc中 role: 'assistant'和role: 'user'用来区分用户和机器人
  //     setDoc((prev: DocCon[]) => {
  //       return [...prev, message];
  //     });
  //   } else {
  //     setLoading(false);
  //     message.error(res.msg);
  //   }
  // };

  //消息队列 使用useRef保存 不会有数据延迟更新问题
  const queue = useRef<any[]>([]);
  //答案接口的轮询状态
  const pollingStatus = useRef<boolean>(false);
  //要添加进doc的消息
  const addMsgContent = useRef<string>('');
  //上一次的消息 用来和当前的消息做对比 筛选出新增的消息内容
  const lastMsgContent = useRef<string>('');

  //将队列里的消息添加到doc里 形成打字机效果
  const addMessage = () => {
    let speed = 45; //打字机的速度
    if (queue.current.length > 0) {
      let currentMsgContent = queue.current[0]; //当前要添加的消息
      const newMsg = addMsgContent.current + currentMsgContent; //将之前的消息和当前的消息拼接
      addMsgContent.current = newMsg; //将拼接后的消息赋值给addMsgContent
      //将拼接后的消息添加到doc中 形成打字机效果
      const addMsg = {
        id: nanoid(),
        uuid: nanoid(),
        content: addMsgContent.current,
        role: 'assistant',
      };
      setDoc((prev: DocCon[]) => {
        return [...prev.slice(0, prev.length - 1), addMsg];
      });
      queue.current.shift(); //已经添加到doc中的消息从队列中删除
    }
    //如果queue.length = 0 且 pollingStatus = false 说明队列中没有消息了 停止递归 并清空addMsgContent
    if (queue.current.length === 0 && !pollingStatus.current) {
      addMsgContent.current = ''; //重置要添加的消息
      setLoading(false);
      setAnswering(false); //关闭正在回答中 展示后台返回的答案
      setIpt(''); //清空输入框
      return;
    }
    //递归添加消息 可以调节递归的时间间隔
    setTimeout(() => {
      addMessage();
    }, speed);
  };

  //过滤掉重复的消息 保留新增的消息
  const filterAdd = (content: any) => {
    //截取content比lastMsgContent的长度 = 后面多出来的内容
    let newAddCon = '';
    if (content.length !== 0) {
      newAddCon = content.slice(lastMsgContent.current.length);
      lastMsgContent.current = content;
    }
    //将新增的消息拆分成单个字符添加到队列中
    for (let i = 0; i < newAddCon.length; i++) {
      queue.current.push(newAddCon[i]);
    }
  };

  //轮询获取答案
  const openPolling = async (id: any) => {
    let speed = 500; //轮询的速度
    const params = {
      id: id,
    };
    //获取答案
    const res = await pollingMsg(params);
    if (res?.code === 0) {
      //如果返回的finished=false 表示还有答案 并且 如果轮询状态开启 继续轮询
      if (!res?.data?.finished && pollingStatus.current) {
        filterAdd(res?.data?.content);
        setTimeout(async () => {
          await openPolling(id);
        }, speed);
      } else {
        filterAdd(res?.data?.content);
        //如果返回的finish_reason = true 停止轮询
        console.log('轮询结束');
        pollingStatus.current = false;
        lastMsgContent.current = '';
      }
    }
  };
  //发送问题
  const createTypewriter = async (id: any, keyword: any) => {
    //预先展示正在回答中
    setLoading(true);
    setAnswering(true);
    //先将用户提出的问题添加到doc来展示
    const userQuestion = {
      id: nanoid(),
      uuid: nanoid(),
      content: keyword,
      role: 'user',
    };
    setDoc((prev: DocCon[]) => {
      return [...prev, userQuestion];
    });

    const params = {
      conversation_id: id,
      content: keyword,
    };
    //发送问题 获取答案的id 用来轮询获取答案
    const res = await messages_comet(params);
    if (res?.code === 0) {
      const { id } = res?.data?.message;
      pollingStatus.current = true; //轮询状态 开启
      //开始轮询获取答案
      await openPolling(id);
      setAnswering(false); //关闭正在回答中 展示后台返回的答案
      const message = {
        id: nanoid(),
        uuid: nanoid(),
        content: '回答中...',
        role: 'assistant',
      };
      //先将回答中添加到doc中展示
      setDoc((prev: DocCon[]) => {
        return [...prev, message];
      });
      addMessage(); //开启 消息队列的递归
    }
  };

  //重置轮询状态 队列 addMsgContent
  const resetPolling = () => {
    pollingStatus.current = false;
    queue.current = [];
    addMsgContent.current = '';
    lastMsgContent.current = '';
  };

  //点击发送按钮
  const handleSubmit = async (keyword: any) => {
    //判断是否有输入
    if (!isNotEmpty(keyword)) {
      message.error('请输入你的问题！');
      return;
    }
    //如果没有会话id 先创建会话
    if (!isNotEmpty(conversationID)) {
      const params = {
        knowledge_base_id: knowledgeId,
      };
      const res = await conversations(params);
      if (res.code === 0) {
        let id = res.data?.conversation?.id;
        setConversationID(id);
        await createTypewriter(id, keyword);
        // await handleCreateMessages(id, keyword);
        changeHistoryList();
      }
      changeNew(false);
    } else {
      //如果有会话id 直接创建打字机信息
      await createTypewriter(conversationID, keyword);
      // await handleCreateMessages(conversationID, keyword);
      changeHistoryList();
    }
  };
  //回车触发提交
  const handleKeyDown = (e: any) => {
    if (e.keyCode === 13) {
      handleSubmit(ipt);
    }
  };

  //获取会话信息列表
  const handleGetMessages = async (id: any) => {
    setLoading(true);
    const params = {
      conversation_id: id,
    };
    const res = await getMessages(params);
    //将数据回显
    if (res.code === 0) {
      setLoading(false);
      let data = res.data?.messages;
      setDoc(data);
    } else {
      setLoading(false);
      message.error(res.msg);
    }
  };

  //跳转到使用指引
  const handleGoToGuide = () => {
    history.push('/guides');
  };

  const [fastQuestionList] = useState<any[]>(questionList); //是否正在回答中
  const handleFastProblem = (data: any) => {
    //去掉 例如：
    let keyword = data.content.replace('例如：', '');
    setIpt(keyword);
  };

  //监听id变化 获取会话信息列表
  useEffect(() => {
    if (id) {
      setConversationID(id);
      handleGetMessages(id);
      setIpt('');
    }
    //id变化时 重置轮询状态 队列 addMsgContent
    resetPolling();
  }, [id]);

  //监听isCreateNew变化 true时清空会话信息
  useEffect(() => {
    if (isCreateNew) {
      setDoc([]);
      setConversationID('');
      setIpt('');
      //id变化时 重置轮询状态 队列 addMsgContent
      resetPolling();
    }
  }, [isCreateNew]);

  //监听isDelCur变化 删除的id等于当前会话id时清空会话信息
  useEffect(() => {
    if (isDelCur === conversationID) {
      setDoc([]);
      setConversationID('');
      //id变化时 重置轮询状态 队列 addMsgContent
      resetPolling();
    }
  }, [isDelCur]);

  useEffect(() => {
    scrollToBottom();
  }, [doc]);

  useEffect(() => {
    if (!loading) {
      if (questionInput.current) {
        questionInput.current.focus();
      }
    }
  }, [loading]);
  return (
    <div className="doc">
      <div className="doc-content" ref={messagesEnd}>
        {doc.length > 0 ? (
          doc.map((item) =>
            item.role === 'user' ? (
              <div className="doc-box" key={item.uuid}>
                <div className="doc-list">
                  <div className="doc-list-hd">
                    <img
                      className="problem-avatar"
                      src={USER_AVATAR}
                      alt=""
                      height={55}
                      width={77}
                    />
                  </div>
                  <div className="doc-list-bd">
                    <div className="problem-con">{item.content}</div>
                  </div>
                </div>
              </div>
            ) : (
              <div className="doc-box" key={item.id}>
                <div className="doc-list">
                  <div className="doc-list-hd">
                    {/* knowledgeId =5 时展示机器人头像 =6时展示用户头像 */}
                    {knowledgeId === 5 ? (
                      <img className="answer-avatar" src={ROBOT_AVATAR} height={55} width={77} />
                    ) : (
                      <img className="answer-avatar" src={ROBOT_AVATAR2} height={55} width={77} />
                    )}
                  </div>
                  <div className="doc-list-bd">
                    {/* div展示内容 */}
                    <div className="answer-con">{item.content}</div>
                    {/* <TextArea
                      defaultValue={item.content}
                      bordered={false}
                      autoSize={true}
                      readOnly={true}
                      className="answer-con"
                    ></TextArea> */}
                  </div>
                </div>
              </div>
            ),
          )
        ) : loading ? (
          <div className="no-doc-box">
            <LoadingOutlined />
          </div>
        ) : knowledgeId === 5 ? (
          <div className="doc-box">
            <div className="doc-list">
              <div className="doc-list-hd">
                {/* knowledgeId =5 时展示机器人头像 =6时展示用户头像 */}
                {knowledgeId === 5 ? (
                  <img className="answer-avatar" src={ROBOT_AVATAR} height={55} width={77} />
                ) : (
                  <img className="answer-avatar" src={ROBOT_AVATAR2} height={55} width={77} />
                )}
              </div>
              <div className="doc-list-bd">
                <div className="answer-con" style={{ width: '100%' }}>
                  <strong>
                    你好，
                    <br />
                    我是SGDT-GLM智能助手。
                  </strong>
                  <p className="robot-info">
                    作为一个运用人工智能大语言模型的机器人，我可以回答你的问题，为你提供有用和专业信息。
                  </p>
                  <p className="robot-info">你可以试着问我：</p>
                  <div className="fast-problem-box">
                    {/* gray时显示expect fast-problem-list样式添加gray */}
                    {fastQuestionList.map((item, index) => {
                      return (
                        <div
                          className={`fast-problem-list  ${item.gray ? 'gray' : 'hover'}`}
                          key={index}
                          onClick={() => !item.gray && handleFastProblem(item)}
                        >
                          {item.gray ? <span className="expect">敬请期待</span> : ''}
                          <div className="fast-problem-hd">{item.title}</div>
                          <div className="fast-problem-bd">{item.content}</div>
                        </div>
                      );
                    })}
                  </div>
                </div>
              </div>
            </div>
          </div>
        ) : (
          <div className="no-doc-box">
            <div className="no-doc">请在下方输入您想咨询的问题吧！</div>
            {/* knowledgeId =5 时展示机器人头像 =6时展示第二个机器人头像 */}
            {knowledgeId === 5 ? (
              <img src={ROBOT_AVATAR} alt="" height={40} width={40} />
            ) : (
              <img src={ROBOT_AVATAR2} alt="" height={40} width={40} />
            )}
          </div>
        )}
        {/* 机器人回答中 在answering=true的时候出现 */}
        {answering && (
          <div className="doc-box">
            <div className="doc-list">
              <div className="doc-list-hd">
                {/* knowledgeId =5 时展示机器人头像 =6时展示用户头像 */}
                {knowledgeId === 5 ? (
                  <img className="answer-avatar" src={ROBOT_AVATAR} height={55} width={77} />
                ) : (
                  <img className="answer-avatar" src={ROBOT_AVATAR2} height={55} width={77} />
                )}
              </div>
              <div className="doc-list-bd">
                <div className="answer-con">回答中...</div>
              </div>
            </div>
          </div>
        )}
      </div>
      <div className="doc-question">
        <div className="question-box">
          <Input
            ref={questionInput}
            value={ipt}
            disabled={loading}
            bordered={false}
            placeholder="请输入你的问题"
            className="question-input"
            onChange={(e) => setIpt(e.target.value)}
            onKeyDown={handleKeyDown}
          />
          <Button
            loading={loading}
            disabled={loading}
            type="primary"
            onClick={() => handleSubmit(ipt)}
            style={{ width: 80 }}
          >
            发送
          </Button>
        </div>
        <div className="agreement-box">
          AI生成内容仅供参考，请遵守
          <span className="agreement-link" onClick={() => handleGoToGuide()}>
            《测试规则》
          </span>
        </div>
      </div>
    </div>
  );
};

export default Doc;
